

(function($){
	var defaultStyle = {
		menu : {
			listStyleType : "none",
			position : "absolute",
			margin : 0,
			cursor : "default",
			zIndex : 20001,
			minWidth: "100px"
		},
		item : {
			color : "black",
			backgroundColor : "white",
			padding : "2 20 2 20",
			whiteSpace : "nowrap"
		},
		hoverItem : {
			color : "white",
			backgroundColor : "#555555"
		},
		containerItem : { // IE 7 doesn't support "data:image/gif;base64" urls
			backgroundImage : "url(images/jquery.n-contextmenu.arrow.gif)",
			backgroundPosition : "95%",
			backgroundRepeat : "no-repeat"
		},
		separator : {
			borderTop : "1px solid darkgray"
		}
	}

	$.fn.contextMenu = function(menu, userStyle, onShow) {
		if (typeof userStyle == "function") {
			onShow = userStyle;
			userStyle = {};
		}
		var style = merge( {}, defaultStyle, userStyle);
		var data = {
			menu : menu,
			style : style,
			onShow : onShow
		};

		this.bind("contextmenu", data, onContextMenu);
		this.bind("click", data, onClick);
//		this.bind("mouseover", data, onMouseOver);
		this.bind("mouseout", data, onMouseOut);
	}

  // TODO: Replace with $.extend(true, ...) when deep copy
  // bug is fixed: http://dev.jquery.com/ticket/1562

	function merge(target) {
		if (!target)
			target = new Object();

		for ( var j = 1; j < arguments.length; j++) {
			var source = arguments[j];

			for ( var i in source) {
				if (source[i] == null)
					continue;
				switch (typeof source[i]) {
				case "string":
				case "number":
				case "boolean":
				case "function":
					target[i] = source[i];
					break;
				default:
					target[i] = merge(target[i], source[i]);
					break;
				}
			}
		}
		return target;
	}

	// Only one context menu should
	// be visible at a time
	var currentMenu;

	function onContextMenu(e, clicked) {
		if (!clicked && currentMenu) {
			return;
		}

		closeCurrentMenu();

		if (typeof (e) == 'undefined') {
			return;
		}
		if (e.data.onShow && e.data.onShow.apply(this, [ e ]) == false)
			return;

		currentMenu = e.data.menu;
		var menuButton = $("#" + $(currentMenu).attr('id') + "-menubutton");
		$(menuButton).addClass('active');
		$(document).bind("click", currentMenu, closeCurrentMenu);
		$(window).bind("blur", currentMenu, closeCurrentMenu);

		hideMenu(e.data.menu);

		var innerWidth = $(window).width();
		if (innerWidth > $(document.body).outerWidth()) {
			innerWidth = $(document.body).outerWidth();
		}

		var leftPos = menuButton.position().left;
		if (leftPos + $(currentMenu).outerWidth() > innerWidth) {
			leftPos = innerWidth - $(currentMenu).outerWidth() - 20;
		}
		
		var topPos = menuButton.position().top + menuButton.innerHeight();
		if (topPos + $(currentMenu).outerHeight() > window.innerHeight + window.scrollY) {
			topPos = menuButton.position().top - $(currentMenu).outerHeight() + 1;
			menuButton.addClass('reversed');
		} else {
			menuButton.removeClass('reversed');
		}
		showMenu(e.data.menu, e.data.style, leftPos, topPos);
		return false;
	}

	function closeCurrentMenu() {
		if (!currentMenu)
			return;

		$(document).unbind("click", currentMenu, closeCurrentMenu);
		$(window).unbind("blur", currentMenu, closeCurrentMenu);
		hideMenu(currentMenu);
		var menuButton = $("#" + $(currentMenu).attr('id') + "-menubutton");
		$(menuButton).removeClass('active');
		currentMenu = null;
	}

	function onClick(e) {
		if (e.button == 0 /* && e.ctrlKey */) {
			return onContextMenu(e, true);
		}
	}

	function onMouseOver(e) {
//		menuTimeoutId = window.setTimeout(onContextMenu, 400, e, false);
		return false;
	}

	function onMouseOut(e) {
//		window.clearTimeout(menuTimeoutId);
		return false;
	}

	function showMenu(menu, style, x, y) {
		menu = $(menu);
		if (menu.is(":visible"))
			return;

		menu.find("ul").css(style.menu).prev("li").css(style.containerItem)
				.end().parent("li").css(style.containerItem);

		menu.find("li").css(style.item).bind("click", onItemClick).bind("mouseenter", style, onItemEnter);

		menu.find("li[separator]").css(style.separator);

		menu.css(style.menu).css("left", x).css("top", y).fadeIn('normal');
		
		var metadata = window.babAddonWidgets.getMetadata(menu.attr('id'));
		
		if (metadata.open) {
			for(var i =0; i < metadata.open.length; i++) {
				var func = metadata.open[i];
				
				eval(func+'(menu)');
			}
		}
	}

	// Hide submenus in reverse order

	function hideMenu(menu) {
		var submenus = $(menu).find("ul").get().reverse();
		$(submenus).hide();
		$(menu).hide();
	}

	function getSubmenu(item) {
		item = $(item);
		var submenu = item.next();
		if (!submenu.is("ul")) {
			submenu = item.children();
		}
		if (submenu.is("ul")) {
			return submenu;
		}
	}

	// Return false for items that have submenus
	// So that clicking on such items doesn't close menu

	function onItemClick(e) {
		if (this == e.target) {
			return !getSubmenu(this);
		}
	}

	function onItemEnter(e) {
		var self = this;
		var style = e.data;
		var menu = $(this).parent();

		menu.children("li").each(
				function() {
					var item = $(this);
					var submenu = getSubmenu(item);
					if (submenu) {
						var x = menu.width();
						var y = item.position().top - 1;
						self == this ? showMenu(submenu, style, x, y)
								: hideMenu(submenu);
					}
					item.css(self == this ? e.data.hoverItem : e.data.item);
				});
	}
})(jQuery);




function widget_menuInit(domNode)
{
	var menusFrame = jQuery('#widgets_hidden_menus_frame');
	if (menusFrame.length < 1) {
		jQuery('body').prepend('<div id="widgets_hidden_menus_frame" style="position: absolute"></div>');
	} else {
		menusFrame.replaceWith('<div id="widgets_hidden_menus_frame" style="position: absolute"></div>');
	}
	// Prepare contextual menus.
	jQuery(domNode).find(".widget-menu").each(function() {
		
		// We create a div to place all context menus.
		menusFrame = jQuery('#widgets_hidden_menus_frame');
		var menuId = this.id;
		var menu = jQuery(this);
		var menuButtonId = menuId + '-menubutton';

		menu.before('<span id="' + menuButtonId + '" class="widget-menu-button"></span>');
		var menuButton = jQuery('#' + menuButtonId);
		menuButton.contextMenu('#' + menuId);
		menu.addClass('widget-popup-menu');
		menu.hide();
		menu.find('.widget-layout-flow-item').after('<br />');

		// We check that the menu is attached (contextual) to a widget.
		if (attachedWidgetId = window.babAddonWidgets.getMetadata(menuId)._attachedWidget) {
			menusFrame.append(menuButton);
			menusFrame.append(menu);
			menuButton.css('opacity', 0.001);
			menuButton.css('position', 'absolute')
						.css('zIndex', 1000);
			var attachedWidget = jQuery('#' + attachedWidgetId);
			
			menuButton.hover(
					function(e) {	
						menuButton.css('opacity', 1);
					},
					function(e) {
						menuButton.css('opacity', 0.001);
					}
			);

			attachedWidget.hover(
					function(e) {
						var leftPos = attachedWidget.position().left + attachedWidget.innerWidth() - menuButton.outerWidth() - 4;
						var topPos = attachedWidget.offset().top;
						menuButton.css('left', leftPos + 'px')
								  .css('top', topPos + 'px')
								  .css('opacity', 0.6);
					},
					function(e) {
						
						menuButton.css('opacity', 0.001);
					}
			);
		}
	});

}


window.bab.addInitFunction(widget_menuInit);
	
